package com.levi.utils;

import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;

/**
 * json工具，基于gson
 * Created by Levi on 2018/3/13.
 */

public class JsonUtils {

    private JsonUtils() {
    }

    private static Gson sGson;

    static {
        sGson = new GsonBuilder()
                .enableComplexMapKeySerialization() //当Map的key为复杂对象时,需要开启该方法
                .serializeNulls() //当字段值为空或null时，依然对该字段进行转换
                .setPrettyPrinting() //对结果进行格式化，增加换行
                .disableHtmlEscaping() //防止特殊字符出现乱码
                .registerTypeAdapter(String.class, new TypeAdapter<String>() {

                    @Override
                    public void write(JsonWriter jsonWriter, String s) throws IOException {
                        jsonWriter.value(s);
                    }

                    @Override
                    public String read(JsonReader jsonReader) throws IOException {
                        JsonToken peek = jsonReader.peek();
                        if (peek == JsonToken.NULL) {
                            jsonReader.nextNull();
                            return "";
                        }
                        if (peek == JsonToken.BOOLEAN) {
                            return Boolean.toString(jsonReader.nextBoolean());
                        }
                        return jsonReader.nextString();
                    }
                })
                .registerTypeAdapter(BigDecimal.class, new TypeAdapter<BigDecimal>() {
                    @Override
                    public void write(JsonWriter jsonWriter, BigDecimal bigDecimal) throws IOException {
                        jsonWriter.value(bigDecimal);
                    }

                    @Override
                    public BigDecimal read(JsonReader jsonReader) throws IOException {
                        if (jsonReader.peek() == JsonToken.NULL) {
                            jsonReader.nextNull();
                            return BigDecimal.ZERO;
                        }
                        try {
                            return new BigDecimal(jsonReader.nextString());
                        } catch (NumberFormatException e) {
                            throw new JsonSyntaxException(e);
                        }
                    }
                })
                .registerTypeAdapter(Boolean.class, new TypeAdapter<Boolean>() {
                    @Override
                    public void write(JsonWriter jsonWriter, Boolean aBoolean) throws IOException {
                        jsonWriter.value(aBoolean);
                    }

                    @Override
                    public Boolean read(JsonReader jsonReader) throws IOException {
                        if (jsonReader.peek() == JsonToken.NULL) {
                            jsonReader.nextNull();
                            return false;
                        }
                        try {
                            return jsonReader.nextInt() == 1;
                        } catch (NumberFormatException e) {
                            throw new JsonSyntaxException(e);
                        }
                    }
                })
                .create();
    }

    /**
     * 对象转json字符串
     *
     * @param src
     * @return
     */
    public static String toJson(Object src) {
        try {
            return sGson.toJson(src);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 对象转json字符串
     *
     * @param src
     * @param type
     * @return
     */
    public static String toJson(Object src, Type type) {
        try {
            return sGson.toJson(src, type);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * json字符串转对象
     *
     * @param json
     * @param clz
     * @param <T>
     * @return
     */
    public static <T> T fromJson(String json, Class<T> clz) {
        try {
            return fromJsonThrowException(json, clz);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T fromJsonThrowException(String json, Class<T> clz) throws Exception {
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        if (String.class.equals(clz)) {
            return (T) json;
        }
        if (Void.class.equals(clz)) {
            return null;
        }
        if (Boolean.class.equals(clz) || boolean.class.equals(clz)) {
            return (T) Boolean.valueOf(json);
        }
        if (Integer.class.equals(clz) || int.class.equals(clz)) {
            return (T) Integer.valueOf(json);
        }
        if (Long.class.equals(clz) || long.class.equals(clz)) {
            return (T) Long.valueOf(json);
        }
        if (Float.class.equals(clz) || float.class.equals(clz)) {
            return (T) Float.valueOf(json);
        }
        if (Double.class.equals(clz) || double.class.equals(clz)) {
            return (T) Double.valueOf(json);
        }
        return sGson.fromJson(json, clz);
    }

    /**
     * json字符串转对象
     *
     * @param json
     * @param type
     * @param <T>
     * @return
     */
    public static <T> T fromJson(String json, Type type) {
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        try {
            if (String.class.equals(type)) {
                return (T) json;
            }
            if (Void.class.equals(type)) {
                return null;
            }
            if (Boolean.class.equals(type) || boolean.class.equals(type)) {
                return (T) Boolean.valueOf(json);
            }
            if (Integer.class.equals(type) || int.class.equals(type)) {
                return (T) Integer.valueOf(json);
            }
            if (Long.class.equals(type) || long.class.equals(type)) {
                return (T) Long.valueOf(json);
            }
            if (Float.class.equals(type) || float.class.equals(type)) {
                return (T) Float.valueOf(json);
            }
            if (Double.class.equals(type) || double.class.equals(type)) {
                return (T) Double.valueOf(json);
            }
            return sGson.fromJson(json, type);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static <T> T fromJsonThrowException(String json, Type type) throws Exception {
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        if (String.class.equals(type)) {
            return (T) json;
        }
        if (Void.class.equals(type)) {
            return null;
        }
        if (Boolean.class.equals(type) || boolean.class.equals(type)) {
            return (T) Boolean.valueOf(json);
        }
        if (Integer.class.equals(type) || int.class.equals(type)) {
            return (T) Integer.valueOf(json);
        }
        if (Long.class.equals(type) || long.class.equals(type)) {
            return (T) Long.valueOf(json);
        }
        if (Float.class.equals(type) || float.class.equals(type)) {
            return (T) Float.valueOf(json);
        }
        if (Double.class.equals(type) || double.class.equals(type)) {
            return (T) Double.valueOf(json);
        }
        return sGson.fromJson(json, type);
    }
}
